<?php

declare(strict_types=1);

namespace Tool\Database;

use PDO;
use PDOStatement;

/**
 * 数据表操作类.
 */
class Table
{
    private ?Connection $conn = null;

    private ?PDOStatement $queryColumnStmt = null;

    public function __construct(Connection $conn)
    {
        $this->conn = $conn;
    }

    public function __destruct()
    {
        $this->conn = null;
        $this->queryColumnStmt = null;
    }

    /**
     * 获取表字段列表.
     */
    public function &getColumnArr(string $dbName, string $tableName): array
    {
        if (is_null($this->queryColumnStmt)) {
            $sql = 'SELECT COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE,COLUMN_COMMENT,COLUMN_KEY,EXTRA FROM `information_schema`.`COLUMNS` WHERE TABLE_SCHEMA=? AND TABLE_NAME=?';
            $this->queryColumnStmt = $this->conn->getPDOStatement($sql);
        }

        $this->queryColumnStmt->execute([$dbName, $tableName]);

        return $this->queryColumnStmt->fetchAll(PDO::FETCH_ASSOC);
    }

    /**
     * 截断表.
     */
    public function truncateTable(string $tableName)
    {
        // ∵表名 字段名 不能使用占位符 只能直接查询
        $sql = 'TRUNCATE TABLE `'.$tableName.'`';
        $this->conn->getPDOStatement($sql)->execute();
    }

    /**
     * 批量新增.
     */
    public function batchInsert(string $tableName, array &$columnArr, array &$data)
    {
        if (!$data) {
            return;
        }

        $sql = [];
        foreach ($data as &$item) {
            $itemSql = [];
            foreach ($columnArr as $column) {
                $itemValue = $item[$column['COLUMN_NAME']];
                $itemSql[] = $this->parseValue($itemValue);
            }
            $sql[] = '('.implode(',', $itemSql).')';
        }

        $columnKeyArr = array_column($columnArr, 'COLUMN_NAME');
        $sql = 'INSERT INTO `'.$tableName.'` (`'.implode('`,`', $columnKeyArr).'`) VALUES '.implode(',', $sql);
        $this->conn->getPDOStatement($sql)->execute();
    }

    protected function parseValue($value): string
    {
        if (is_null($value)) {
            return 'null';
        }

        if (is_int($value)) {
            return (string) $value;
        }

        if (is_bool($value)) {
            return (string) $value;
        }

        return '"'.$value.'"';
    }
}
